package com.zzyl.nursing.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.constant.HttpStatus;
import com.zzyl.common.core.page.TableDataInfo;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.nursing.domain.Reservation;
import com.zzyl.nursing.dto.ReservationDto;
import com.zzyl.nursing.mapper.ReservationMapper;
import com.zzyl.nursing.service.IReservationService;
import com.zzyl.nursing.vo.TimeCountVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;

/**
 * 预约信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-06-07
 */
@Service
@Slf4j
public class ReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements IReservationService
{
    @Autowired
    private ReservationMapper reservationMapper;

    /**
     * 查询预约信息
     * 
     * @param id 预约信息主键
     * @return 预约信息
     */
    @Override
    public Reservation selectReservationById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询预约信息列表
     * 
     * @param reservation 预约信息
     * @return 预约信息
     */
    @Override
    public List<Reservation> selectReservationList(Reservation reservation)
    {
        return reservationMapper.selectReservationList(reservation);
    }

    /**
     * 新增预约信息
     * 
     * @param reservation 预约信息
     * @return 结果
     */
    @Override
    public int insertReservation(Reservation reservation)
    {
        return save(reservation) ? 1 : 0;
    }

    /**
     * 修改预约信息
     * 
     * @param reservation 预约信息
     * @return 结果
     */
    @Override
    public int updateReservation(Reservation reservation)
    {
        return updateById(reservation) ? 1 : 0;
    }

    /**
     * 批量删除预约信息
     * 
     * @param ids 需要删除的预约信息主键
     * @return 结果
     */
    @Override
    public int deleteReservationByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除预约信息信息
     * 
     * @param id 预约信息主键
     * @return 结果
     */
    @Override
    public int deleteReservationById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }
    
    /**
     * 统计指定时间范围内的预约数量
     * 
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 预约数量统计
     */
    @Override
    public List<TimeCountVo> countReservationsForTime(LocalDateTime startTime, LocalDateTime endTime) {
        return reservationMapper.countReservationsForTime(startTime, endTime);
    }
    
    /**
     * 批量更新预约状态
     * 
     * @param ids 预约ID列表
     */
    @Override
    public void batchUpdateStatus(List<Long> ids) {
        reservationMapper.batchUpdateStatus(ids);
    }
    
    /**
     * 查询当天用户取消的预约数量
     * 
     * @param userId 用户ID
     * @return 取消的预约数量
     */
    @Override
    public int getCancelledReservationCount(Long userId) {
        // 获取当天的开始时间和结束时间
        LocalDate today = LocalDate.now();
        LocalDateTime startTime = today.atStartOfDay();
        LocalDateTime endTime = today.atTime(LocalTime.MAX);
        
        // 构建查询条件
        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getStatus, 2) // 状态为取消
               .eq(Reservation::getUpdateBy, userId) // 用户ID
               .between(Reservation::getUpdateTime, startTime, endTime); // 更新时间在当天
        
        // 查询数量
        return Math.toIntExact(count(wrapper));
    }
    
    /**
     * 查询指定日期预约时间段剩余次数
     * 
     * @param time 日期时间戳
     * @return 时间段剩余次数列表
     */
    @Override
    public List<TimeCountVo> countByTime(Long time) {
        // 将时间戳转换为LocalDateTime
        LocalDateTime dateTime = LocalDateTime.ofInstant(
            java.time.Instant.ofEpochMilli(time), 
            java.time.ZoneId.systemDefault()
        );
        
        // 获取指定日期的开始和结束时间
        LocalDate date = dateTime.toLocalDate();
        LocalDateTime startTime = date.atStartOfDay();
        LocalDateTime endTime = date.atTime(LocalTime.MAX);
        
        // 查询指定日期范围内的预约时间段剩余次数
        return reservationMapper.countReservationsForTime(startTime, endTime);
    }
    
    /**
     * 新增预约
     * 
     * @param reservationDto 预约信息
     * @return 是否成功
     */
    @Override
    public boolean addReservation(ReservationDto reservationDto) {
        // 获取当前登录用户ID
        Long userId = UserThreadLocal.getUserId();
        if (userId == null) {
            throw new RuntimeException("用户未登录");
        }
        
        // 转换DTO为实体
        Reservation reservation = new Reservation();
        reservation.setName(reservationDto.getName());
        reservation.setMobile(reservationDto.getMobile());
        reservation.setTime(reservationDto.getTime());
        reservation.setVisitor(reservationDto.getVisitor());
        reservation.setType(reservationDto.getType());
        reservation.setStatus(0); // 默认状态为待报道
        reservation.setCreateBy(String.valueOf(userId));
        reservation.setUpdateBy(String.valueOf(userId));
        
        // 保存预约信息
        return save(reservation);
    }
    
    /**
     * 分页查询预约
     * 
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @param status 状态
     * @return 分页结果
     */
    @Override
    public TableDataInfo pageQuery(Integer pageNum, Integer pageSize, Integer status) {
        // 获取当前登录用户ID
        Long userId = UserThreadLocal.getUserId();
        if (userId == null) {
            throw new RuntimeException("用户未登录");
        }
        
        // 构建查询条件
        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getCreateBy, String.valueOf(userId)); // 只查询当前用户的预约
        if (status != null) {
            wrapper.eq(Reservation::getStatus, status); // 按状态筛选
        }
        wrapper.orderByDesc(Reservation::getCreateTime); // 按创建时间降序排序
        
        // 分页查询
        IPage<Reservation> page = new Page<>(pageNum, pageSize);
        page = page(page, wrapper);
        
        // 封装分页信息
        TableDataInfo rspData = new TableDataInfo();
        rspData.setCode(HttpStatus.SUCCESS);
        rspData.setMsg("请求成功");
        rspData.setRows(page.getRecords());
        rspData.setTotal(page.getTotal());
        
        return rspData;
    }
    
    /**
     * 取消预约
     * 
     * @param id 预约ID
     * @return 是否成功
     */
    @Override
    public boolean cancelReservation(Long id) {
        // 获取当前登录用户ID
        Long userId = UserThreadLocal.getUserId();
        if (userId == null) {
            throw new RuntimeException("用户未登录");
        }
        
        // 查询预约信息
        Reservation reservation = getById(id);
        if (reservation == null) {
            throw new RuntimeException("预约不存在");
        }
        
        // 验证是否是当前用户的预约
        if (!String.valueOf(userId).equals(reservation.getCreateBy())) {
            throw new RuntimeException("无权操作此预约");
        }
        
        // 验证预约状态是否可取消（只有待报道状态可以取消）
        if (reservation.getStatus() != 0) {
            throw new RuntimeException("当前状态不可取消");
        }
        
        // 更新预约状态为取消
        reservation.setStatus(2); // 2表示取消
        reservation.setUpdateBy(String.valueOf(userId));
        reservation.setUpdateTime(new Date());
        
        // 保存更新
        return updateById(reservation);
    }
    
    /**
     * 查找过期的预约ID列表
     * 
     * @return 过期预约ID列表
     */
    @Override
    public List<Long> findExpiredReservationIds() {
        log.info("开始查找过期的预约...");
        
        // 查询状态为0（待报道）且预约时间小于当前时间的预约
        LambdaQueryWrapper<Reservation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Reservation::getStatus, 0) // 状态为待报道
               .lt(Reservation::getTime, LocalDateTime.now()) // 预约时间小于当前时间
               .select(Reservation::getId); // 只查询ID字段
        
        List<Reservation> expiredReservations = list(wrapper);
        List<Long> expiredIds = expiredReservations.stream()
                .map(Reservation::getId)
                .collect(Collectors.toList());
        
        log.info("找到过期预约数量: {}", expiredIds.size());
        return expiredIds;
    }
    
    /**
     * 更新过期预约状态（定时任务使用）
     * 
     * @return 更新的记录数
     */
    @Override
    public int updateExpiredReservations() {
        log.info("开始执行更新过期预约状态的定时任务...");
        
        // 查找过期的预约ID
        List<Long> expiredIds = findExpiredReservationIds();
        
        if (expiredIds.isEmpty()) {
            log.info("没有找到过期的预约，本次任务结束");
            return 0;
        }
        
        try {
            // 批量更新状态为过期(3)
            batchUpdateStatus(expiredIds);
            log.info("成功更新 {} 条过期预约状态为过期", expiredIds.size());
            return expiredIds.size();
        } catch (Exception e) {
            log.error("更新过期预约状态失败: ", e);
            throw new RuntimeException("更新过期预约状态失败", e);
        }
    }
} 